#include <iostream>
#include <utility>
#include <vector>

template< typename Type > struct type_descriptor;

template<>
struct type_descriptor<void> 
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) {
		return str << "void"; 
	}
};

template<>
struct type_descriptor<int> 
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) {
		return str << "int"; 
	}
};

template<typename Type,int N>
struct type_descriptor<Type [N]> 
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) {
		return str << "[ array of " << N << " " << type_descriptor<Type> () << " ]";
	}
};

template< typename Ret, typename Arg >
struct type_descriptor<Ret (Arg)> 
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) {
		return str << "[ function ( " << type_descriptor<Arg> () << " ) to " << type_descriptor<Ret> () << " ]";
	}
};



template<typename Type>
struct type_descriptor<Type *>
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) { 
		return str << "[ pointer to " << type_descriptor<Type> () << " ]"; 
	}
};

template<typename Type>
struct type_descriptor<Type &>
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) { 
		return str << "[ reference to " << type_descriptor<Type> () << " ]"; 
	}
};

template<typename Type>
struct type_descriptor<Type const>
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) { 
		return str << "[ const " << type_descriptor<Type> () << " ]";
	}
};


template<typename T1, typename T2>
struct type_descriptor< std::pair<T1,T2> >
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) { 
		return str << "[ pair < " << type_descriptor<T1> () << " , " << type_descriptor<T2> ()  << " > ]"; 
	}
};


template<typename Type>
struct type_descriptor< std::vector<Type> >
{
	friend std::ostream & operator << ( std::ostream & str,  type_descriptor ) { 
		return str << "[ vector < " << type_descriptor<Type> () << " > ]"; 
	}
};

